<template>
  <div class="area-view">
    <!-- 顶部站点切换和导出 -->
    <SiteAndExport @changeSite="handleChangeSite" :params="params" :interface="'getAreaData'" :chartInstances="[myChart]" />
    <!-- 时间选择 -->
    <div class="date-select">
      <div class="select-left">
        <span>时间范围：</span>
        <TypeSelect v-model:value="dateType" :typeList="dateTypeList" />
        <el-date-picker v-model="dateRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" class="date-picker" />
      </div>
    </div>
    <div class="content-box" v-loading="chartLoading">
      <div class="content-left">
        <RankCard :data="rankData" />
      </div>
      <div :style="{ width: chartType == 'bar' ? '100%' : '60%' }">
        <div ref="chart" style="height: 680px; width: 100%"></div>
      </div>
      <div class="content-right">
        <div class="chart-btns">
          <el-tooltip content="地图" placement="bottom" effect="light">
            <a :class="{ active: chartType === 'map' }" href="javascript:;" @click="changeChart('map')"><i class="iconfont">&#xe705;</i></a>
          </el-tooltip>
          <el-tooltip content="柱图" placement="bottom" effect="light">
            <a :class="{ active: chartType === 'bar' }" href="javascript:;" @click="changeChart('bar')"><i class="iconfont">&#xe703;</i></a>
          </el-tooltip>
          <el-tooltip content="环形图" placement="bottom" effect="light">
            <a :class="{ active: chartType === 'pie' }" href="javascript:;" @click="changeChart('pie')"><i class="iconfont">&#xe701;</i></a>
          </el-tooltip>
        </div>
        <div class="province-card" v-if="provinceShow && chartType != 'bar'">
          <div class="card-header">
            <div class="header-name">{{ provinceName }}</div>
            <i class="iconfont close-card" @click="handleClose">&#xe8e7;</i>
          </div>
          <div class="card-body">
            <div class="list-item" v-for="(item, index) in cityData" :key="index">
              <span>{{ item.name }}</span>
              <span>{{ item.value }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref, reactive, watch, nextTick } from 'vue'
import TypeSelect from './components/TypeSelect.vue'
import RankCard from './components/RankCard.vue'
import SiteAndExport from './components/SiteAndExport.vue'
import { getStationAreaData } from '@/api/log'
import { getStartAndEndTimes, applyOpacityArray } from '@/utils/tools'
import { useStore } from 'vuex'
import chinaMap from '@/assets/china.json'
import echarts from '@/utils/echarts'
echarts.registerMap('china', { geoJSON: chinaMap })

const store = useStore()
const siteId = ref(store.state.site.currentSite?.id)
const chartLoading = ref(false)
//切换站点
const handleChangeSite = val => {
  params.siteId = val
  getData()
}
//查询时间选择
const dateRange = ref('')
const dateType = ref(0)
const dateTypeList = ref([
  { value: 0, label: '今日' },
  { value: 1, label: '昨日' },
  { value: 2, label: '近7日' },
  { value: 3, label: '近30天' },
  { value: 4, label: '近3月' },
  { value: 5, label: '近1年' },
  { value: 6, label: '总计' }
])
watch(
  dateType,
  newVal => {
    dateRange.value = getStartAndEndTimes(newVal)
  },
  { deep: true, immediate: true }
)
watch(dateRange, () => {
  if (dateRange.value && dateRange.value[0]) {
    params.startTime = dateRange.value[0].getTime()
    params.endTime = dateRange.value[1].getTime()
  } else {
    params.startTime = ''
    params.endTime = ''
  }
  getData()
})
//排名和地图数据
const rankData = ref([])
const allData = ref({
  total: 0,
  mapData: [],
  rankData: []
})
//搜索参数
const defaultRange = getStartAndEndTimes(0)
const params = reactive({
  siteId: siteId.value,
  startTime: defaultRange[0].getTime(),
  endTime: defaultRange[1].getTime()
})
const getData = async () => {
  chartLoading.value = true
  try {
    let res = await getStationAreaData(params)
    allData.value.mapData = res.data
    allData.value.rankData = res.data
  } catch {
    chartLoading.value = false
  }
  chartLoading.value = false
}
watch(
  allData,
  newVal => {
    if (provinceShow.value) {
      provinceShow.value = false
    }
    myChart.value.setOption(getOption(chartType.value, allData.value.mapData))
    rankData.value = newVal.rankData.slice(0, 10)
  },
  { deep: true }
)
//地图点击事件,右侧展示省份城市数据
const cityData = ref([])
const provinceName = ref()
const provinceShow = ref(false)
const handleMap = params => {
  if (chartType.value == 'bar') return
  cityData.value = params.data.children
  provinceName.value = params.data.name
  provinceShow.value = true
}
//关闭城市排名卡片
const handleClose = () => {
  provinceShow.value = false
  cityData.value = []
}
//自定义地图类型切换
const chartType = ref('')
const changeChart = type => {
  chartType.value = type
}
watch(chartType, () => {
  chartLoading.value = true
  provinceShow.value = false
  myChart.value.clear()
  myChart.value.setOption(getOption(chartType.value, allData.value.mapData))
  if (chartType.value == 'bar') {
    nextTick(() => {
      myChart.value.resize()
    })
  }
  chartLoading.value = false
})
//获取地图颜色分段配置(分5段)
let themeColor = ref(getComputedStyle(document.documentElement).getPropertyValue(`--el-color-primary`))
let colorArr = applyOpacityArray(themeColor.value, [0.1, 0.3, 0.5, 0.7, 0.9])
const getPieces = () => {
  const maxValue = allData.value.mapData.reduce((prev, curr) => {
    return curr.value > prev ? curr.value : prev
  }, 0)
  const minValue = allData.value.mapData.reduce((min, current) => {
    if (current.value > 0 && current.value < min.value) {
      return current.value
    } else {
      return min
    }
  }, 1)
  let splitRange = Math.ceil((maxValue - minValue) / 5)
  let pieces = []
  for (var i = 0; i < 5; i++) {
    var startValue = minValue + splitRange * i
    var endValue = minValue + splitRange * (i + 1)
    pieces.push({
      min: startValue,
      max: endValue,
      color: colorArr[i]
    })
  }
  return pieces
}
//地图配置和初始化
let myChart = ref(null)
const chart = ref(null)
const getMapOption = chartData => {
  return {
    tooltip: {
      textStyle: {
        color: '#333333'
      },
      borderWidth: 0,
      backgroundColor: '#ffffff',
      formatter: function (params) {
        if (params.name === '南海诸岛') {
          return // 不展示tooltip
        }
        if (params.data && params.data.value) {
          return params.name + '<br>访问量：' + params.data.value
        } else {
          return params.name
        }
      }
    },
    geo: {
      map: 'china',
      zoom: 1.1,
      top: 90,
      left: 100,
      label: {
        show: true,
        fontSize: '12',
        color: 'rgba(0,0,0,0.5)'
      },
      itemStyle: {
        borderColor: 'rgba(0, 0, 0, 0.2)'
      },
      emphasis: {
        itemStyle: {
          areaColor: themeColor.value
        }
      }
    },
    visualMap: {
      type: 'piecewise',
      show: false,
      pieces: getPieces()
    },
    series: [
      {
        type: 'map',
        geoIndex: 0,
        data: chartData
      }
    ]
  }
}
const getBarOption = chartData => {
  return {
    grid: {
      top: '118px'
    },
    tooltip: {
      trigger: 'axis',
      backgroundColor: '#ffffff',
      borderWidth: 1,
      formatter: params => {
        let str = params[0].name + '<br>访问量: ' + params[0].value
        return str
      },

      textStyle: {
        color: '#333333'
      },
      extraCssText: 'z-index:2'
    },
    xAxis: {
      data: chartData.map(item => item.name),
      axisLine: {
        show: true,
        lineStyle: {
          color: '#eeeeee'
        }
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        color: '#333333',
        fontSize: 12,
        interval: 0
        // rotate: 10
      }
    },
    yAxis: [
      {
        type: 'value',
        name: '访问量',
        nameTextStyle: {
          color: '#333333',
          fontSize: 14,
          fontWeight: 600
        },
        nameGap: 30, // 表现为上下位置
        axisLine: {
          show: true,
          lineStyle: {
            color: '#eeeeee'
          }
        },
        axisTick: {
          show: false
        },
        axisLabel: {
          color: '#333333',
          fontSize: 14
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#eeeeee'
          }
        },
        splitArea: {
          show: true, //分割区域
          areaStyle: {
            color: ['#F8F8F8', '#fff']
          }
        }
      }
    ],
    series: [
      {
        type: 'bar',
        barWidth: '18px',
        barCategoryGap: '100%',
        zlevel: 2,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(
            0,
            0,
            0,
            1,
            [
              {
                offset: 0,
                color: themeColor.value
              },
              {
                offset: 1,
                color: colorArr[2]
              }
            ],
            false
          )
        },
        label: {
          show: true,
          fontSize: 13,
          color: '#aaaaaa',
          position: 'top'
        },
        data: chartData.map(item => item.value)
      }
    ]
  }
}
const getPieOption = chartData => {
  return {
    tooltip: {
      show: true,
      textStyle: {
        color: '#333333',
        fontSize: 14
      },
      backgroundColor: '#ffffff',
      formatter(params) {
        if (params.name === '') {
          return ''
        }
        return `${params.name} : ${params.percent}%`
      }
    },
    series: [
      {
        type: 'pie',
        left: '0',
        radius: ['40%', '70%'],
        center: ['50%', '50%'], // 修改为居中
        avoidLabelOverlap: true,
        label: {
          color: '#333333',
          alignTo: 'labelLine',
          formatter: '{name|{b}}\n{num|{c}}次 {zb|{d}}%',
          minMargin: 5,
          edgeDistance: 10,
          lineHeight: 15,
          rich: {
            num: {
              fontSize: 12,
              color: '#333333' //数值颜色
            },
            zb: {
              fontSize: 12,
              color: '#333333'
            }
          }
        },
        labelLine: {
          length: 15,
          length2: 0,
          maxSurfaceAngle: 80
        },
        data: chartData
      },
      {
        type: 'pie',
        radius: '0%',
        center: ['50%', '50%'],
        label: {
          position: 'center',
          color: '#333333',
          fontSize: 18
        },
        data: [
          {
            name: '总计: ' + allData.value.mapData.reduce((prev, curr) => prev + curr.value, 0),
            value: allData.value.mapData.reduce((prev, curr) => prev + curr.value, 0)
          }
        ],
        silent: true
      }
    ]
  }
}
const getOption = (chartType, chartData) => {
  switch (chartType) {
    case 'map':
      return getMapOption(chartData)
    case 'bar':
      return getBarOption(chartData)
    case 'pie':
      return getPieOption(chartData)
    default:
      return getMapOption(chartData)
  }
}
onMounted(() => {
  myChart.value = echarts.init(chart.value)
  chartType.value = 'map'
  getData()
  window.onresize = function () {
    myChart.value.resize()
  }
  myChart.value.off('click')
  myChart.value.on('click', function (params) {
    handleMap(params)
  })
})
</script>

<style lang="scss" scoped>
.area-view {
  padding: 20px;
  background: #ffffff;
  .date-select {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .select-left {
      display: flex;
      align-items: center;
      span {
        margin-right: 10px;
      }
      .date-picker {
      }
      ::v-deep .el-input__wrapper {
        margin-left: 20px;
        width: 340px;
      }
    }
    .select-right {
    }
  }
  .content-box {
    position: relative;
    display: flex;
    .content-left {
      flex-shrink: 0;
      width: 320px;
    }
    .content-right {
      position: absolute;
      right: 0;
      width: 20%;
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      .chart-btns {
        margin-top: 37px;
        height: 32px;
        width: 96px;
        box-sizing: border-box;
        border: var(--el-border);
        border-radius: 4px;
        display: flex;
        overflow: hidden;
        a {
          display: flex;
          width: 50%;
          height: 100%;
          align-items: center;
          justify-content: center;
        }
        a.active {
          background-color: $mainColor;
          i {
            color: #fff;
          }
        }
      }
      .province-card {
        margin-top: 40px;
        width: 300px;
        box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
        color: #333333;
        .card-header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: 17px 20px;
          border-bottom: 1px solid #e4e4e4;
          font-size: 16px;
          .close-card {
            cursor: pointer;
          }
        }
        .card-body {
          padding: 0 10px 30px 20px;
          height: 400px;
          overflow-y: scroll;
          .list-item {
            display: flex;
            justify-content: space-between;
            padding: 18px 0;
            border-bottom: 1px solid #e4e4e4;
            font-size: 14px;
          }
        }
        .card-body::-webkit-scrollbar {
          width: 10px; /* 设置滚动条的宽度 */
          background-color: #f2f2f2 !important; /* 设置滚动条的背景颜色 */
        }
        .card-body::-webkit-scrollbar-thumb {
          background-color: #f2f2f2; /* 设置滚动条的滑块颜色 */
        }
        .card-body::-webkit-scrollbar-thumb:hover {
          background-color: #d9d9d9; /* 设置滑块的鼠标悬停颜色 */
        }
        .card-body::-webkit-scrollbar-track {
          background-color: transparent; /* 设置滚动条的轨道颜色 */
        }
        .card-body::-webkit-scrollbar-button {
          display: none;
        }
      }
    }
  }
}
</style>
